# -*- coding: utf-8 -*-

import os
from ldap import LDAPError
from django.utils.datastructures import MultiValueDictKeyError
from django.contrib.auth import login
from django.contrib.auth import logout
from django.contrib.sessions import *
from django.http import HttpResponse
from django.http import HttpResponseForbidden
from django.http import HttpResponseNotFound
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render_to_response
from django.template import RequestContext, loader
from labmin.webapp.forms import *
from labmin.webapp.filters import *
from labmin.webapp.models import Admin
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from labmin.labminldap.StudentDaoLDAP import *
from labmin.labminldap.LDAPDataConnector import *
from labmin.executor.sshexec import *
from labmin.executor.coord import *
import ConfigParser
from django.conf import settings

__ldapConfigurator = ConfigParser.ConfigParser()
__ldapConfigurator.read('/home/slawek/public_html/labmin/config/labmin.conf')


def not_found(request):
    t = loader.get_template('404.html')
    c = RequestContext(request, {})
    return HttpResponseNotFound(t.render(c))

def forbidden(request):
    t = loader.get_template('403.html')
    c = RequestContext(request, {})
    return HttpResponseForbidden(t.render(c))

def main(request):
    return render_to_response('main.html', context_instance=RequestContext(request));

def shell(request):
    return render_to_response('shell.html', context_instance=RequestContext(request));

def login(request):
    try:
        if request.session['user']:
            return HttpResponseRedirect('/')
    except KeyError:
        pass
    try:
        login = request.POST['login']
        password = request.POST['password']
    except KeyError:
        return HttpResponseRedirect('/')
    try:
        user = Admin.objects.get(login = login)
    except:
        user = None
    if user is not None:
        if user.comparePassword(password):
            request.session['user'] = user
            return HttpResponseRedirect('/')
        else:
            return render_to_response('main.html', {
                "password_error": True
            }, context_instance=RequestContext(request));
    else:
        return render_to_response('main.html', {
            "login_error": True
        }, context_instance=RequestContext(request));

def logout(request):
    if request.session.get('user', False):
        del request.session['user']
    return HttpResponseRedirect('/')


######## STUDENTS ########

def students_list(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    students = Student.objects.all()
    if request.method == 'POST':
        filter_login = request.POST['filter_login']
        filter_1=StudentFilter()

        filter = {'login' : filter_login}
        students = filter_1.applyFilter(filter, students)
    return render_to_response('students_list.html', {
        'objects': students
    }, context_instance=RequestContext(request));


def student_form(request, student_pk=None):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if student_pk is not None:
        student = get_object_or_404(Student, pk=student_pk)
        page_title = 'edycja danych studenta'
    else:
        student = None
        page_title = 'dodawanie studenta'
    form = StudentForm(data=request.POST or None, instance=student)
    if request.method == 'POST':
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/students_list')
    return render_to_response('form.html', {
        'form': form,
        'page_title': page_title
    }, context_instance=RequestContext(request))


def show_student(request, student_pk):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')

    student = Student.objects.get(pk=student_pk)
    error = None
    LDAPstudent = None
    try:
        connector = LDAPDataConnector(__ldapConfigurator)
        LDAPsearcher = StudentDaoLDAP(connector, __ldapConfigurator)

        student = Student.objects.get(pk=student_pk)
        LDAPstudents = LDAPsearcher.searchStudent(student.email)
        if len(LDAPstudents) == 0:
            error = "Nie znaleziono studenta"
        else:
            #zakładamy, że wyszukowanie zwróciło jednego studenta
            LDAPstudents[0][1]['cn'][0] = unicode(LDAPstudents[0][1]['cn'][0])
            LDAPstudents[0][1]['mail'] = unicode(LDAPstudents[0][1]['mail'][0])
            LDAPstudents[0][1]['faculty'] = unicode(LDAPstudents[0][1]['faculty'][0])
            LDAPstudents[0][1]['year'] = unicode(LDAPstudents[0][1]['year'][0])

            LDAPstudent = LDAPstudents[0][1]
    except LDAPError, e:
        error = e.message['desc']

    return render_to_response('show_student.html', {
        'student': student,
		'LDAPstudent': LDAPstudent,
        'error': error
    }, context_instance=RequestContext(request))


def delete_students(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')

    if request.method == 'POST':
        list = request.POST.getlist('list')
        student_pk = request.POST['student_pk']
        if not student_pk == '':
            list = [student_pk]
        for student_pk in list:
            student = get_object_or_404(Student, pk=student_pk)
            student.delete()
        return HttpResponseRedirect('/students_list')
    return not_found(request)


######## STUDENT GROUPS ########

def student_groups_list(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if request.GET.has_key('show'):
        if request.GET['show'] == 'all':
            student_groups = StudentGroup.objects.all()
    else:
        student_groups = StudentGroup.objects.filter(admin = request.session['user'])

    paginator = Paginator(student_groups, 4)
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    try:
        student_groups = paginator.page(page)
    except (EmptyPage, InvalidPage):
        student_groups = paginator.page(paginator.num_pages)

    return render_to_response('student_groups_list.html', {
        'objects': student_groups
    }, context_instance=RequestContext(request))


def student_group_form(request, student_group_pk=None):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if student_group_pk is not None:
        student_group = get_object_or_404(StudentGroup, pk=student_group_pk)
        page_title = 'edycja grupy studentów'
    else:
        student_group = None
        page_title = 'tworzenie grupy studentów'
    form = StudentGroupForm(data=request.POST or None, instance=student_group, auto_id = False)

    if request.method == 'POST':
        if not request.POST.getlist('list'):
            if form.is_valid():
                new_student_group = form.save()
                request.session['user'].student_groups.add(new_student_group)
                return HttpResponseRedirect('/student_groups_list')
        else:	#jeśli przekazujemy listę studentów, z których tworzymy grupę
            form = StudentGroupForm(initial={'students':request.POST.getlist('list')}, auto_id = False)
    return render_to_response('form.html', {
        'form': form,
        'page_title': page_title
    }, context_instance=RequestContext(request))


def show_student_group(request, student_group_pk):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    student_group = StudentGroup.objects.get(pk=student_group_pk)
    if student_group in request.session['user'].student_groups.all():
        associated_with_user = True
    else:
        associated_with_user = False
    return render_to_response('show_student_group.html', {
        'student_group': student_group,
		'associated_with_user': associated_with_user
    }, context_instance=RequestContext(request))


def delete_student_group(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if request.method == 'POST':
        student_group_pk = request.POST['student_group_pk']
        student_group = get_object_or_404(StudentGroup, pk=student_group_pk)
        student_group.delete()
        return HttpResponseRedirect('/student_groups_list')
    return not_found(request)


######## ADMINS ########

def admins_list(request):
    try:
        if not request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    admins = Admin.objects.all()

    paginator = Paginator(admins, 4)
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    try:
        admins = paginator.page(page)
    except (EmptyPage, InvalidPage):
        admins = paginator.page(paginator.num_pages)
    
    return render_to_response('admins_list.html', {
        'objects': admins
    }, context_instance=RequestContext(request))


def admin_form(request, admin_pk=None):
    try:
        if not request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if admin_pk is not None:
        admin = get_object_or_404(Admin, pk=admin_pk)
        page_title = 'edycja danych administratora'
    else:
        admin = None
        page_title = 'dodawanie administratora'
    form = AdminForm(data=request.POST or None, instance=admin, auto_id=False)
    if request.method == 'POST' and form.is_valid():
        admin = form.save(commit=False)
        admin.setPassword(form.data['password'])
        admin.save()
        form.save_m2m()
        return HttpResponseRedirect('/admins_list')
    return render_to_response('form.html', {
        'form': form,
        'page_title': page_title
    }, context_instance=RequestContext(request))


def show_admin(request, admin_pk):
    try:
        if not request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    admin = Admin.objects.get(pk=admin_pk)
    return render_to_response('show_admin.html', {
        'admin': admin
    }, context_instance=RequestContext(request))


def delete_admin(request):
    try:
        if not request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if request.method == 'POST':
        admin_pk = request.POST['admin_pk']
        admin = get_object_or_404(Admin, pk=admin_pk)
        admin.delete()
        return HttpResponseRedirect('/admins_list')
    return not_found(request)


def add_student_group_to_admin(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    
    if request.method == 'POST':
        admin = request.session['user']
        student_group_pk = request.POST['student_group_pk']
        student_group = StudentGroup.objects.get(pk = student_group_pk)
        admin.student_groups.add(student_group)
        admin.save()
        return HttpResponseRedirect('/student_groups_list')
    return not_found(request)


def remove_student_group_from_admin(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    
    if request.method == 'POST':
        admin = request.session['user']
        student_group_pk = request.POST['student_group_pk']
        student_group = StudentGroup.objects.get(pk = student_group_pk)
        admin.student_groups.remove(student_group)
        admin.save()
        return HttpResponseRedirect('/student_groups_list')
    return not_found(request)


def add_service_group_to_admin(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    
    if request.method == 'POST':
        admin = request.session['user']
        service_group_pk = request.POST['service_group_pk']
        service_group = ServiceGroup.objects.get(pk = service_group_pk)
        admin.service_groups.add(service_group)
        admin.save()
        return HttpResponseRedirect('/service_groups_list')
    return not_found(request)


def remove_service_group_from_admin(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    
    if request.method == 'POST':
        admin = request.session['user']
        service_group_pk = request.POST['service_group_pk']
        service_group = ServiceGroup.objects.get(pk = service_group_pk)
        admin.service_groups.remove(service_group)
        admin.save()
        return HttpResponseRedirect('/service_groups_list')
    return not_found(request)


######## SERVICES ########

def services_list(request):
    services = Service.objects.all()

    paginator = Paginator(services, 4)
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    try:
        services = paginator.page(page)
    except (EmptyPage, InvalidPage):
        services = paginator.page(paginator.num_pages)
    
    return render_to_response('services_list.html', {
        'objects': services
    }, context_instance=RequestContext(request))


def service_form(request, service_pk=None):
    try:
        if not request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if service_pk is not None:
        service = get_object_or_404(Service, pk=service_pk)
        page_title = 'edycja usługi'
    else:
        service = None
        page_title = 'dodawanie usługi'
    form = ServiceForm(data=request.POST or None, files=request.FILES or None, instance=service)
    if request.method == 'POST' and form.is_valid():
        try:
            script_file = request.FILES['script_file']
        except MultiValueDictKeyError:
            script_file = None
        if script_file is not None:
            if service and service.script_file and os.path.exists(service.script_file.path):
                os.remove(service.script_file.path)
        form.save()
        return HttpResponseRedirect('/services_list')
    return render_to_response('form.html', {
        'form': form,
        'page_title': page_title
    }, context_instance=RequestContext(request))


def show_service(request, service_pk):
    service = Service.objects.get(pk=service_pk)
    return render_to_response('show_service.html', {
        'service': service
    }, context_instance=RequestContext(request))


def delete_services(request):
    try:
        if not request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')

    if request.method == 'POST':
        list = request.POST.getlist('list')
        service_pk = request.POST['service_pk']
        if not service_pk == '':
            list = [service_pk]
        for service_pk in list:
            service = get_object_or_404(Service, pk=service_pk)
            service.delete()
        return HttpResponseRedirect('/services_list')
    return not_found(request)


######## SERVICE GROUPS ########

def service_groups_list(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')

    if request.GET.has_key('show'):
        if request.GET['show'] == 'all':
            service_groups = ServiceGroup.objects.all()
    else:
        service_groups = ServiceGroup.objects.filter(admin = request.session['user'])

    paginator = Paginator(service_groups, 4)
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    try:
        service_groups = paginator.page(page)
    except (EmptyPage, InvalidPage):
        service_groups = paginator.page(paginator.num_pages)

    return render_to_response('service_groups_list.html', {
        'objects': service_groups
    }, context_instance=RequestContext(request))


def service_group_form(request, service_group_pk=None):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if service_group_pk is not None:
        service_group = get_object_or_404(ServiceGroup, pk=service_group_pk)
        page_title = 'edycja grupy usług'
    else:
        service_group = None
        page_title = 'tworzenie grupy usług'
    form = ServiceGroupForm(data=request.POST or None, instance=service_group, auto_id = False)

    if request.method == 'POST':
        if not request.POST.getlist('list'):
            if form.is_valid():
                new_service_group = form.save()
                request.session['user'].service_groups.add(new_service_group)
                return HttpResponseRedirect('/service_groups_list')
        else:	#jeśli przekazujemy listę studentów, z których tworzymy grupę
            form = ServiceGroupForm(initial={'services':request.POST.getlist('list')}, auto_id = False)
    return render_to_response('form.html', {
        'form': form,
        'page_title': page_title
    }, context_instance=RequestContext(request))


def show_service_group(request, service_group_pk):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    service_group = ServiceGroup.objects.get(pk=service_group_pk)
    if service_group in request.session['user'].service_groups.all():
        associated_with_user = True
    else:
        associated_with_user = False
    return render_to_response('show_service_group.html', {
        'service_group': service_group,
        'associated_with_user': associated_with_user
    }, context_instance=RequestContext(request))


def delete_service_group(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    if request.method == 'POST':
        service_group_pk = request.POST['service_group_pk']
        service_group = get_object_or_404(ServiceGroup, pk=service_group_pk)
        service_group.delete()
        return HttpResponseRedirect('/service_groups_list')
    return not_found(request)


######## STUDENT-SERVICE ASSOCIATIONS ########

def student_service_association_form(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')

    form = StudentServiceAssociationForm()
    if request.method == 'POST':#and form.is_valid()
        student_group_name = request.POST['student_group']
        service_group_name = request.POST['service_group']
        student_group = StudentGroup.objects.get(name = student_group_name)
        service_group = ServiceGroup.objects.get(name = service_group_name)
        students_list = student_group.students.all()
        services_list = service_group.services.all()

        for service in services_list:
            logger = Logger()
            coordinator = Coordinator(service.name);
	    print settings.MEDIA_ROOT+service.script_file.name
	    f=open(settings.MEDIA_ROOT+service.script_file.name,'r')
	    lines=f.readlines()
	    scrpt='\n'.join(lines)
	    f.close()
            logger.logGlobal('Transakcja rozpoczęta', request.session['user'].login, 'Labmin', [None, None])
            for student in students_list:
                existing_associations = StudentServiceAssociation.objects.filter(student = student).filter(service = service)
                if not existing_associations:
                    association = StudentServiceAssociation(student = student, service = service, is_active = True)
                    association.save()
                else:
                    print '[DEBUG] skojarzenie ' + student.login + ' z ' + service.name + ' juz istnieje'
            result = coordinator.coordinate(scrpt, students_list, [service.ip_address])
            logger.logGlobal('Transakcja zakończona', request.session['user'].login, 'Labmin', [None, None])
        return user_password_list(request, result)
    return render_to_response('form.html', {
        'form': form,
        'page_title': 'przypisywanie studentom usług'
    }, context_instance=RequestContext(request))


def user_password_list(request, result):
    paginator = Paginator(result, 4)
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    try:
        result = paginator.page(page)
    except (EmptyPage, InvalidPage):
        result = paginator.page(paginator.num_pages)
    return render_to_response('result.html', {
        'objects': result
    }, context_instance=RequestContext(request))



######## LOGS ########

def logs_list(request):
    try:
        if request.session['user'].is_superadmin:
            return forbidden(request)
    except KeyError:
        return HttpResponseRedirect('/')
    logs = Log.objects.all()

    paginator = Paginator(logs, 20)
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    try:
        logs = paginator.page(page)
    except (EmptyPage, InvalidPage):
        logs = paginator.page(paginator.num_pages)
    
    return render_to_response('logs_list.html', {
        'objects': logs
    }, context_instance=RequestContext(request))
